package com.six.backend.controller;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.six.backend.pojo.LoginLog;
import com.six.backend.annotation.OperLog;
import com.six.backend.pojo.User;
import com.six.backend.service.UserService;
import com.six.backend.shiro.Utils.Result;
import com.six.backend.token.JwtToken;
import com.six.backend.utils.*;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.RedisConnectionFailureException;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author skyler
 */
@RestController
@Slf4j
@Transactional(rollbackFor=Exception.class)
@RequestMapping(value = "/user",produces = "application/json;charset = utf-8")
public class UserController {
    @Autowired
    private UserService userService;

    @Autowired
    private RedisUtil redisUtil;


    @PostMapping("/login")
    @ResponseBody
    @ApiOperation("登录")
    @OperLog(operModule = "用户模块",operType = "post",operDesc = "用户登录操作")
    public String selectUserByAccount(@RequestBody User user, HttpServletRequest request, HttpSession session) {
        if(user.getAccount() == null ||user.getPassword() == null) {
            return JSON.toJSONString(new Result<>().setCode(500).setMessage("用户名和密码错误"));
        }
        Subject subject = SecurityUtils.getSubject();
        String jwt = JwtUtil.createJWT(user.getAccount(),"back","user",1000*60*60*24);
        JwtToken jwtToken = new JwtToken(jwt,user.getPassword());
        try {
            subject.login(jwtToken);
        }catch (UnknownAccountException e) {
            return JSON.toJSONString(new Result<>().setCode(401).setMessage("账号不存在"));
        }catch (IncorrectCredentialsException e) {
            return JSON.toJSONString(new Result<>().setCode(401).setMessage("密码不存在"));
        }
        User backUser = userService.selectUserByAccount(user);
        if (!backUser.getStatus()) {
            return JSON.toJSONString(new Result<>().setCode(202).setMessage("用户被禁用，无法登录，请联系管理员"));
        }
        session.setAttribute("user",backUser.getAccount());
        String ipAddr = ipUtils.getIpAddr(request);
        userService.insertLoginLog(backUser.getAccount(),ipAddr,new SimpleDateFormat("yyy-MM-dd HH:mm:ss").format(new Date()));
        Map<String,Object> map = new HashMap<>();
        map.put("user",backUser);
        map.put("token",jwt);
        return JSON.toJSONString(new Result<>().setCode(200).setMessage("登录成功").setData(map));
    }

    @PostMapping("/getMenuList")
    @ApiOperation("获取homepage侧边导航栏")
    @ResponseBody
    @OperLog(operModule = "用户模块",operType = "post",operDesc = "获取侧边导航栏操作")
    public Result getMenuList(HttpServletRequest request) {
        String account = TokenUtil.getTokenName(request);
        if(account == null) {
            return new Result<>().setCode(401).setMessage("未登录");
        }
        String role = userService.selectUserRole(account);
        // 获取导航栏缓存
        Object o = null;
        try {
            o = redisUtil.get(role);
            if (o != null) {
                return new Result<>().setCode(200).setData(o).setMessage("菜单获取成功");
            }else {
                List<Map<String,Object>> list = userService.getMenuList(account);
                // 将得到的导航栏数据写入redis，有效时间设为10分钟
                redisUtil.set(role, JSON.toJSON(list),600);
                return new Result<>().setCode(200).setData(list).setMessage("菜单获取成功");
            }
        } catch (Exception e) { // 捕获Redis连接异常
            System.out.println("未连接到Redis！");
            return new Result<>().setCode(200).setData(userService.getMenuList(account)).setMessage("菜单获取成功");
        }

    }



    @PostMapping("/addUser")
    @ApiOperation("新建用户")
    @OperLog(operModule = "用户模块",operType = "post",operDesc = "新建用户操作")
    public Result addUser(@RequestBody Map map,HttpServletRequest request){
        String account = TokenUtil.getTokenName(request);
        if (map.get("account") == null || map.get("password") == null || map.get("name") == null) {
            return new Result<>().setCode(406).setMessage("用户名或密码为空");
        }
        if (userService.isExist(map.get("account").toString())) {
            return new Result<>().setCode(202).setMessage("用户已存在");
        }
        // 设置新建时间
        map.put("createTime", new TimeUtil().getTime());
        //密码加密
        map.put("password", EncryptUtil.encrypt(map.get("password").toString()));
        if (map.get("roleName") != null) {
            userService.insertUserRole(map);
        }
        if (userService.insertUser(map)) {
            return new Result<>().setCode(201).setMessage("新建成功");
        }
        return new Result<>().setCode(406).setMessage("插入失败");
    }

    @GetMapping("/getUser")
    @ApiOperation("查看用户")
    @OperLog(operModule = "用户模块",operType = "get",operDesc = "查看用户操作")
    public Result getUser(@RequestParam(value = "account",required = false) String account,
                          @RequestParam(value = "status",required = false) Boolean status,
                          @RequestParam(value = "name",required = false) String name,
                          @RequestParam(value = "pageNum",required = false) Integer pageNum,
                          @RequestParam(value = "pageSize",required = false) Integer pageSize){
        Map map = new HashMap();
        map.put("account",account);
        map.put("status",status);
        map.put("name",name);
        if (pageNum != null && pageSize != null) {
            PageHelper.startPage(pageNum,pageSize);
            return new Result<>().setCode(200).setMessage("查询成功").setData(new PageInfo<User>(userService.selectUser(map)));
        }
        return new Result<>().setCode(200).setMessage("查询成功").setData(userService.selectUser(map));

    }

    @DeleteMapping("/deleteUser")
    @ApiOperation("删除用户")
    @OperLog(operModule = "用户模块",operType = "delete",operDesc = "删除用户操作")
    public Result deleteUser(@RequestParam(value = "account") @Valid String account){
        if (userService.deleteUser(account)) {
            return new Result<>().setCode(200).setMessage("删除成功");
        }else {
            return new Result<>().setMessage("删除失败").setCode(202);
        }
    }

    @GetMapping("/getUserLog")
    @ApiOperation("查询登录日志")
    @OperLog(operModule = "用户模块",operType = "get",operDesc = "查询用户登录日志操作")
    public Result selectLoginLog(@RequestParam(value = "account", required = false) String account,
                                 @RequestParam(value = "pageNum",required = false) @NotNull(message = "pageNum不能为空") Integer pageNum,
                                 @RequestParam(value = "pageSize",required = false) @NotNull(message = "pageSize不能为空") Integer pageSize) {
        HashMap map = new HashMap<>();
        map.put("account",account);
        if (pageNum != null && pageSize != null) {
            PageHelper.startPage(pageNum,pageSize);
        }
        List<LoginLog> loginLog = userService.selectLoginLog(map);
        return new Result<>().setCode(200).setMessage("请求成功").setData(new PageInfo<>(loginLog));
    }

    @PutMapping("/editUser")
    @ApiOperation("编辑用户")
    @OperLog(operModule = "用户模块",operType = "put",operDesc = "编辑用户信息操作")
    public Result editUser(@RequestBody Map map) {
        if (userService.updateUser(map)) {
            return new Result<>().setCode(200).setMessage("修改成功");
        }
        return new Result<>().setCode(202).setMessage("信息一致，无需修改");
    }

    @PostMapping("/changeStatus")
    @ApiOperation("改变用户状态")
    public Result changeStatus(@RequestBody User user) {
        if (userService.updateStatus(user)) {
            return new Result<>().setCode(200).setMessage("用户状态修改成功");
        }
        return new Result<>().setCode(202).setMessage("用户状态修改失败");
    }


    @PostMapping("/changePassword")
    @ApiOperation("修改密码")
    @OperLog(operModule = "用户模块",operType = "post",operDesc = "修改密码操作  ")
    public Result changePassword(@RequestBody Map map) {
        if (!map.get("newPassword").equals(map.get("checkPass"))) {
            return new Result<>().setCode(202).setMessage("密码不一致");
        }
        // 密码加密
        map.put("password",EncryptUtil.encrypt(map.get("newPassword").toString()));
        if (userService.updatePassword(map)) {
            return new Result<>().setCode(200).setMessage("密码修改成功");
        }
        return new Result<>().setCode(202).setMessage("密码修改失败");
    }

}